package com.syh.jn.scm.infrastructure.repository.impl.upstream.finance;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.wrapper.Wrapper;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.syh.core.ddd.infrastructure.repository.AbstractAggregateRepository;
import com.syh.jn.scm.domain.upstream.entity.finance.UpStatementAccountBill;
import com.syh.jn.scm.domain.upstream.entity.finance.UpStatementAccountBillItem;
import com.syh.jn.scm.domain.upstream.repository.finance.UpStatementAccountBillRepository;
import com.syh.jn.scm.dto.supplier.finance.statementAccountBill.StatementAccountBillItemVo;
import com.syh.jn.scm.dto.upstream.finance.UpStatementAccountBillItemVo;
import com.syh.jn.scm.dto.upstream.finance.UpStatementAccountBillVo;
import com.syh.jn.scm.infrastructure.repository.model.finance.StatementAccountBillItemModel;
import com.syh.jn.scm.infrastructure.repository.model.finance.StatementAccountBillModel;
import com.syh.jn.scm.infrastructure.repository.utils.MybatisTemplate;
import com.syh.jn.scm.infrastructure.repository.utils.SQLAliasGenerateUtil;
import com.syh.jn.scm.infrastructure.wrapper.BaseResolve;
import com.syh.jn.scm.infrastructure.wrapper.ResolveToSQL;
import org.apache.ibatis.jdbc.SQL;
import org.hibernate.Query;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Repository
public class UpStatementAccountBillRepositoryImpl extends AbstractAggregateRepository<UpStatementAccountBill,StatementAccountBillModel,Long> implements UpStatementAccountBillRepository {


  @Override
  public Long add(UpStatementAccountBill bill) {
    Long billId = super.add(bill);
    bill.setId(billId);
    this.saveItems(bill);
    return billId;
  }

  @Override
  public void update(UpStatementAccountBill bill) {
    super.update(bill);
    if (bill.getUpStatementAccountBillItems() != null) {
      this.removeItemsByBillId(bill.getId());
      this.saveItems(bill);
    }
  }

  private void saveItems(UpStatementAccountBill bill) {
    bill.getUpStatementAccountBillItems().forEach(item -> {
      StatementAccountBillItemModel itemModel = new StatementAccountBillItemModel();
      ExtBeanUtils.copyProperties(item, itemModel);
      itemModel.setStatementAccountBillId(bill.getId());
      itemModel.setBusinessEntityId(bill.getBusinessEntityId());
      super.hibernateTemplate.save(itemModel);
    });
  }

  @Override
  public UpStatementAccountBill getById(Long aLong) {
    UpStatementAccountBill bill = super.getById(aLong);
    if (bill == null) {
      return bill;
    }
    List<StatementAccountBillItemModel> itemModels = (List<StatementAccountBillItemModel>) this.hibernateTemplate
            .find("from StatementAccountBillItemModel model where model.statementAccountBillId = ?", aLong);
    List<UpStatementAccountBillItem> billItems = new ArrayList<>();
    itemModels.forEach(itemModel -> {
      billItems.add(ExtBeanUtils.copyProperties(itemModel, new UpStatementAccountBillItem(), true));
    });
    bill.setUpStatementAccountBillItems(billItems);
    return bill;
  }

  @Override
  public void removeById(Long aLong) {
    this.removeItemsByBillId(aLong);
    super.removeById(aLong);
  }

  @Override
  public void remove(UpStatementAccountBill bill) {
    this.removeItemsByBillId(bill.getId());
    super.remove(bill);
  }
  private void removeItemsByBillId(Long billId) {
    String hql = "delete StatementAccountBillItemModel model where model.statementAccountBillId = :statementAccountBillId";
    Query query = super.buildQuery(hql);
    query.setParameter("statementAccountBillId", billId);
    query.executeUpdate();
  }
  /**
   * 上传单据图片
   * @param bill
   */
  @Override
  public void upload(UpStatementAccountBill bill) {
    super.update(bill);
  }

  @Override
  protected Class getViewObject() {
    return UpStatementAccountBillVo.class;
  }

  @Override
  protected SQL getViewSql() {
    return new SQL(){{
      SELECT(SQLAliasGenerateUtil.aliasGenerate(StatementAccountBillModel.class, "upStatementBill", null),
              "supplier.NAME AS businessEntityName");
      FROM("T_FINANCE_STATEMENT_ACCOUNT_BILL AS upStatementBill");
      LEFT_OUTER_JOIN("T_BASE_SUPPLIER AS supplier ON supplier.ID = upStatementBill.BUSINESS_ENTITY_ID");
      LEFT_OUTER_JOIN("(" +
              " SELECT GROUP_CONCAT(SOURCE_CODE) AS sourceCode, " +
              " STATEMENT_ACCOUNT_BILL_ID AS billId"  +
              " FROM " +
              " T_FINANCE_STATEMENT_ACCOUNT_BILL_ITEM " +
              " GROUP BY STATEMENT_ACCOUNT_BILL_ID " +
              " )statementItem ON statementItem.billId = upStatementBill.ID ");
    }};
  }

  @Override
  protected BaseResolve getViewWrapperResolve(Wrapper wrapper) {
    Map<String,String> map = new HashMap<>();
    map.put("id","upStatementBill.ID");
    map.put("customerType","upStatementBill.CUSTOMER_TYPE");
    map.put("customerId","upStatementBill.CUSTOMER_ID");
    map.put("financeState","upStatementBill.FINANCE_STATE");
    map.put("businessState","upStatementBill.BUSINESS_STATE");
    map.put("ticketState","upStatementBill.TICKET_STATE");
    map.put("inputTimestamp","upStatementBill.INPUT_TIMESTAMP");
    map.put("code", "upStatementBill.CODE");
    map.put("sourceCode", "statementItem.sourceCode");
    map.put("state", "upStatementBill.STATE");
    map.put("ticketState", "upStatementBill.TICKET_STATE");
    ResolveToSQL parse = new ResolveToSQL(wrapper, (propertyName) -> {
      return map.get(propertyName);
    });
    return parse;
  }

  //sql
  private SQL getSql(Long statementId) {
    return new SQL() {{
      SELECT(
              SQLAliasGenerateUtil.aliasGenerate(StatementAccountBillItemModel.class, "item", null)
      );
      FROM("( select * from T_FINANCE_STATEMENT_ACCOUNT_BILL_ITEM WHERE (SOURCE_TYPE = 0 OR SOURCE_TYPE = 1 OR SOURCE_TYPE = 2 OR SOURCE_TYPE = 3 OR SOURCE_TYPE = 4 OR SOURCE_TYPE = 5)) item");
      LEFT_OUTER_JOIN("T_FINANCE_COST_BILL cost on cost.ID = item.SOURCE_ID");
      LEFT_OUTER_JOIN("T_FINANCE_INCOME_BILL inCome on inCome.ID = item.SOURCE_ID");
      LEFT_OUTER_JOIN("T_PUR_PURCHASE_ORDER pur on pur.ID = item.SOURCE_ID");
      LEFT_OUTER_JOIN("T_SALE_ORDER sale on sale.ID = item.SOURCE_ID");
      LEFT_OUTER_JOIN("T_PUR_PURCHASE_RETURN_ORDER purRet on purRet.ID = item.SOURCE_ID");
      LEFT_OUTER_JOIN("T_SALE_RETURN_ORDER saleRet on saleRet.ID = item.SOURCE_ID");
      WHERE("item.STATEMENT_ACCOUNT_BILL_ID = " + statementId);
    }};
  }

  /**
   * 根据对账单id获取明细
   *
   * @param statementId 对账单id
   * @return
   */
  @Override
  public List<UpStatementAccountBillItemVo> getItemsByStatementId(Long statementId) {
    List<Map<String, Object>> list = MybatisTemplate.selectList(this.getSql(statementId).toString());
    List<UpStatementAccountBillItemVo> upStatementAccountBillItemVos = JSONArray.parseArray(JSONObject.toJSONString(list), UpStatementAccountBillItemVo.class);
    return upStatementAccountBillItemVos;
  }
}
